package com.example.authority.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.authority.annotations.ClearPerms;
import com.example.authority.common.Result;

import com.example.authority.entity.*;
import com.example.authority.service.AddressService;
import com.example.authority.service.GoodsService;
import com.example.authority.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.aspectj.weaver.ast.Or;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.List;


import com.example.authority.service.OrderService;


/**
 * @program: authority-hm-0.0.1
 * @ClassName:OrderController
 * @description: OrderController前端控制器
 * @author:dyy
 * @Version 3.0
 **/
@Tag(name = "订单管理 前端控制器")
@RestController
@RequestMapping("/order")
public class OrderController {

    @Resource
    private OrderService orderService;
    @Resource
    private GoodsService goodsService;
    @Resource
    private UserService userService;
    @Resource
    private AddressService addressService;

    /**
     * 新增
     *
     * @param order
     * @return
     */
    @Operation(summary = "新增")
    @PostMapping
    public Result save(@RequestBody Order order) {

        User user = userService.getUserInfo();
        order.setUsername(user.getUsername());
        Goods goods = goodsService.getById(order.getGid());
        // 格式化日期时间
        String formattedDateTime = DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss");
        String uniqueId = IdUtil.randomUUID();
        // 组合日期时间和唯一ID
        String orderId = formattedDateTime + "-" + uniqueId.substring(0, 6).toUpperCase();
        order.setTotal(goods.getPrice() * order.getScount());
        order.setName(orderId);
        order.setGoods(JSONUtil.toJsonStr(goods));
        Address address = new Address();
        if (order.getAid() == 0) {
            address = addressService.getOne(new LambdaQueryWrapper<Address>().eq(Address::getIsDefault, 1).eq(Address::getUsername, user.getUsername()));
        } else {
            address = addressService.getById(order.getAid());
        }
        order.setAid(address.getId());
        order.setAddress(JSONUtil.toJsonStr(address));
        return Result.success(orderService.save(order));
    }

    /**
     * 修改
     *
     * @param order
     * @return
     */
    @Operation(summary = "修改")
    @PutMapping("/{id}")
    public Result update(@PathVariable Long id, @RequestBody Order order) {

        return Result.success(orderService.updateById(order));
    }

    /**
     * 支付计算
     *
     * @param id
     * @param aid
     * @param scount
     * @return
     */
    @Operation(summary = "支付")
    @PutMapping("/apply/{id}/{aid}/{scount}")
    @ClearPerms
    public Result apply(@PathVariable Long id, @PathVariable Long aid, @PathVariable Integer scount) {
//      计算用户账户余额
        Goods goods = goodsService.getById(id);
        User user = userService.getUserInfo();
        if ((goods.getPrice() * scount - user.getBalance()) > 0) {
            throw new RuntimeException("账户余额不足,请充值!");
        }


//      计算库存
        if (goods.getStore() - scount < 0) {
            throw new RuntimeException("库存不足!");
        }
//        判断是否上架
        if (goods.getIsShow() == 0) {
            throw new RuntimeException("商品已经下架!");
        }
//      设置商品销量库存
        goods.setSales(goods.getSales() + scount);
        goods.setStore(goods.getStore() - scount);
//        扣款
        user.setBalance(user.getBalance() - goods.getPrice() * scount);
//        查询地址信息
        Address address = new Address();
        if (aid == 0) {
            address = addressService.getOne(new LambdaQueryWrapper<Address>().eq(Address::getIsDefault, 1).eq(Address::getUsername, user.getUsername()));
        } else {
            address = addressService.getById(aid);
        }
//        保存订单
        Order order = new Order();
        order.setUsername(user.getUsername());
        // 格式化日期时间
        String formattedDateTime = DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss");
        String uniqueId = IdUtil.randomUUID();
        // 组合日期时间和唯一ID
        String orderId = formattedDateTime + "-" + uniqueId.substring(0, 6).toUpperCase();
        order.setName(orderId);
        order.setGid(goods.getId());
        order.setGoods(JSONUtil.toJsonStr(goods));
        order.setAid(address.getId());
        order.setScount(scount);
        order.setTotal(goods.getPrice() * scount);
        order.setAddress(JSONUtil.toJsonStr(address));
        order.setStatu(2);
        orderService.saveOrUpdate(order);
        userService.saveOrUpdate(user);
        goodsService.saveOrUpdate(goods);
        return Result.success();
    }

    @Operation(summary = "支付")
    @PutMapping("/apply/update/{scount}/{oid}")
    @ClearPerms
    public Result applyByorder(@PathVariable Integer scount, @PathVariable Long oid) {
        Order order = orderService.getById(oid);
//      计算用户账户余额
        Goods goods = goodsService.getById(order.getGid());
        User user = userService.getUserInfo();
        if ((goods.getPrice() * order.getScount() - user.getBalance()) > 0) {
            throw new RuntimeException("账户余额不足,请充值!");
        }


//      计算库存
        if (goods.getStore() - order.getScount() < 0) {
            throw new RuntimeException("库存不足!");
        }
//        判断是否上架
        if (goods.getIsShow() == 0) {
            throw new RuntimeException("商品已经下架!");
        }
//      设置商品销量库存
        goods.setSales(goods.getSales() + order.getScount());
        goods.setStore(goods.getStore() - order.getScount());
//        扣款
        user.setBalance(user.getBalance() - goods.getPrice() * order.getScount());
//        查询地址信息
        Address address = new Address();


        order.setStatu(2);
        orderService.saveOrUpdate(order);
        userService.saveOrUpdate(user);
        goodsService.saveOrUpdate(goods);
        return Result.success();
    }

    /**
     * 查询所有Order
     *
     * @return
     */
    @Operation(summary = "查询所有Order")
    @GetMapping
    public Result findAll() {
        return Result.success(orderService.list());
    }

    /**
     * 获取单个
     *
     * @param id
     * @return
     */
    @Operation(summary = "获取单个")
    @GetMapping("/{id}")
    public Result findOne(@PathVariable Integer id) {

        Order order = orderService.getById(id);
        if (order.getStatu() == 1) {
            Goods goods = goodsService.getById(order.getGid());
            order.setGoods(JSONUtil.toJsonStr(goods));
        }
        Address address = addressService.getById(order.getAid());
        order.setAddress(JSONUtil.toJsonStr(address));
        return Result.success(order);
    }

    /**
     * 分页显示
     *
     * @param name
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Operation(summary = "分页显示")
    @GetMapping("/page")
    public Result findPage(
            @RequestParam(defaultValue = "") String name,
            @RequestParam(defaultValue = "") Integer statu,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize) {
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        if (!"".equals(name)) {
            queryWrapper.like("name", name);

        }
        if (statu != null&&statu!=0) {
            queryWrapper.eq("statu", statu);
        }
        if (StpUtil.hasRole("user")){
            queryWrapper.eq("username",userService.getUserInfo().getUsername());
        }
        queryWrapper.orderByDesc("id");
        Page<Order> page = orderService.page(new Page<>(pageNum, pageSize), queryWrapper);
        List<Order> records = page.getRecords();
        for (Order order : records) {
            if (order.getStatu() == 0) {
                Goods goods = goodsService.getById(order.getGid());
                Address address = addressService.getById(order.getAid());
                order.setAddress(JSONUtil.toJsonStr(address));
                order.setGoods(JSONUtil.toJsonStr(goods));
            }
        }
        page.setRecords(records);
        return Result.success(page);
    }

    /**
     * 单个删除
     *
     * @param id
     * @return
     */
    @Operation(summary = "单个删除")
    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id) {
        return Result.success(orderService.removeById(id));
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @Operation(summary = "批量删除")
    @DeleteMapping("/batch/{ids}")
    @Transactional
    public Result deleteByIds(@PathVariable String[] ids) {
        return Result.success(orderService.removeByIds(Arrays.asList(ids)));
    }

    /**
     * 批量导出
     * 使用的技术为alibaba下面的easyexcel
     * 写数据
     *
     * @param ids
     * @return
     */
    @Operation(summary = "批量导出")
    @GetMapping("/batch/export/{ids}")
    public void exportByIds(@PathVariable String[] ids, HttpServletResponse response) throws IOException {

        List<Order> list = orderService.listByIds(Arrays.asList(ids));
        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("order导出数据", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), Order.class).sheet("sheel1").doWrite(list);

    }

    /**
     * 批量导入
     * 使用的技术为alibaba下面的easyexcel
     * 读数据
     *
     * @param
     */
    @Operation(summary = "批量导入")
    @PostMapping("/batch/upload")
    public Result writeExcel(MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(), Order.class, new PageReadListener<Order>(dataList -> {
            dataList.forEach(entity -> orderService.save(entity.toBuilder().id(null).build()));
        })).sheet().doRead();
        return Result.success();
    }

}